package com.ajzhang.dao;


import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.impl.CriteriaImpl;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class BaseDao<T> extends HibernateDaoSupport{
	public void delete(T o) {
		this.getHibernateTemplate().delete(o);
	}
	public void insert(T o) {
		this.getHibernateTemplate().save(o);
	}

	public T select(Class cls, Serializable id){
		return (T) this.getHibernateTemplate().get(cls, id);
	}
	public void update(T o) {
		this.getHibernateTemplate().update(o);
	}
	
	public void merge(T o) {
		this.getHibernateTemplate().merge(o);
	}
	
	public List<T> getAll(String className) {
		String queryString = "from "+className;
		return this.getHibernateTemplate().find(queryString);
	}
	
	public List<T> getAllByQuery(String queryString) {
		return this.getHibernateTemplate().find(queryString);
	}
	
	public Query getQuery(final String queryStr)
	    throws DataAccessException {
		Query query = (Query) getHibernateTemplate().execute(
		        new HibernateCallback() {
		            public Object doInHibernate(Session session) {
		                return session.createQuery(queryStr);
		            }
		        });
		return query;
	}
	
	public List<T> getListByQuery(final String queryString,final int pageSize,final int pageIndex) {
//		Query query = this.getHibernateTemplate().getSessionFactory().getCurrentSession().createQuery(queryString);
		Query query = getQuery(queryString);
		query.setFirstResult(pageIndex * pageSize);
		query.setMaxResults(pageSize);
		return query.list();
	}

	public List<T> findByProperty(String className, String propertyName,
			Object value) throws Exception {
		String queryString = "from "+className+" where "+propertyName+" =?";
		return this.getHibernateTemplate().find(queryString,value);
	}
	
	public int findByCriteriaCount(final DetachedCriteria detachedCriteria){
		return (Integer) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)throws HibernateException {
				Criteria criteria = detachedCriteria.getExecutableCriteria(session);
				return ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();
			}
		}, true);
	}
	
	public Map<String,Object> findPageByCriteria(final DetachedCriteria detachedCriteria,final int pageSize,final int pageIndex)throws Exception {
		return (Map<String,Object>) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)throws HibernateException {
				Criteria criteria = detachedCriteria.getExecutableCriteria(session);
				List items = criteria.setFirstResult(pageIndex * pageSize).setMaxResults(pageSize).list();
				int totalCount = items.size();
				if(totalCount >= pageSize){
					//移除order   chanHo 20080415
					List orderEntrys=null;
					Field field=null;

					CriteriaImpl impl = (CriteriaImpl) criteria;
					try {
						field = CriteriaImpl.class.getDeclaredField("orderEntries");
						field.setAccessible(true);//这是关键：）
						orderEntrys = (List)field.get(impl);
						field.set(criteria,new ArrayList()); 
					} catch (Exception e) {
						e.printStackTrace();
					} 
					
					criteria.setProjection(null);
					criteria.setFirstResult(0).setMaxResults(1);
					totalCount = ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();
					criteria.setProjection(null);
					criteria.setProjection(null);
					criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY); 
					//恢復order , 不過不建議重用detachedCriteria ,目前Criteria有很多問�?後面的代碼可以注釋掉
					/* List innerOrderEntries = null;
					try {
						innerOrderEntries = (List)field.get(criteria);
					} catch (Exception e) {
						e.printStackTrace();
					}
					for(int i=0;i<orderEntrys.size();i++){
						innerOrderEntries.add(orderEntrys.get(i));
					} */
				}
				Map reyurnMap = new HashMap<String,Object>();
				reyurnMap.put("count", totalCount);
				reyurnMap.put("page", items);
				return reyurnMap;
			}
		}, true);
	} 
	
	public Map<String,Object> findPageByCriteriaTwo(final DetachedCriteria detachedCriteria,final int pageSize,final int recordFrom){
		return (Map<String,Object>) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)throws HibernateException {
				Criteria criteria = detachedCriteria.getExecutableCriteria(session);
				List items = criteria.setFirstResult(recordFrom).setMaxResults(pageSize).list();
				int totalCount = items.size();
				if(totalCount >= pageSize){
					//移除order   chanHo 20080415
					List orderEntrys=null;
					Field field=null;
					
					CriteriaImpl impl = (CriteriaImpl) criteria;
					try {
						field = CriteriaImpl.class.getDeclaredField("orderEntries");
						field.setAccessible(true);//这是关键：）
						orderEntrys = (List)field.get(impl);
						field.set(criteria,new ArrayList()); 
					} catch (Exception e) {
						e.printStackTrace();
					} 
					
					criteria.setProjection(null);
					criteria.setFirstResult(0).setMaxResults(1);
					totalCount = ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();
					criteria.setProjection(null);
					criteria.setProjection(null);
					criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY); 
				}else{
					List orderEntrys=null;
					Field field=null;
					
					CriteriaImpl impl = (CriteriaImpl) criteria;
					try {
						field = CriteriaImpl.class.getDeclaredField("orderEntries");
						field.setAccessible(true);//这是关键：）
						orderEntrys = (List)field.get(impl);
						field.set(criteria,new ArrayList()); 
					} catch (Exception e) {
						e.printStackTrace();
					} 
					criteria.setProjection(null);
					criteria.setFirstResult(0).setMaxResults(1);
					totalCount = criteria.setProjection(Projections.rowCount()).uniqueResult() == null ? 0 : ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();
				}
				Map reyurnMap = new HashMap<String,Object>();
				reyurnMap.put("count", totalCount);
				reyurnMap.put("page", items);
				return reyurnMap;
			}
		}, true);
	}
	
	public List<T> findPageByCriteriaOrderBy(final DetachedCriteria detachedCriteria,final int pageSize,final int pageIndex)throws Exception {
		return (List<T>) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)throws HibernateException {
				Criteria criteria = detachedCriteria.getExecutableCriteria(session);
				List items = criteria.setFirstResult(pageIndex * pageSize).setMaxResults(pageSize).list();
				return items;
			}
		}, true);
	} 

	public List<T> findByCriteria(DetachedCriteria detachedCriteria)
			throws Exception {
		return this.getHibernateTemplate().findByCriteria(detachedCriteria);
	}
}
